#include "util/format/u_format.h"
#include "vulkan/util/vk_format.h"

#include "agxv_private.h"


/* TODO: UABI, fake for macOS */
#ifndef DRM_FORMAT_MOD_LINEAR
#define DRM_FORMAT_MOD_LINEAR 1
#endif
#define DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER (2)

VKAPI_ATTR VkResult VKAPI_CALL
agxv_CreateImage(VkDevice _device,
                 const VkImageCreateInfo *pCreateInfo,
                 const VkAllocationCallbacks *pAllocator,
                 VkImage *pImage)
{
    AGXV_FROM_HANDLE(agxv_device, device, _device);
    struct agxv_image *image;

    // const VkImageSwapchainCreateInfoKHR *swapchain_info =
    //     vk_find_struct_const(pCreateInfo->pNext, IMAGE_SWAPCHAIN_CREATE_INFO_KHR);
    // if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE)
    //     return create_image_from_swapchain(device, pCreateInfo, swapchain_info,
    //                                        pAllocator, pImage);

    image = vk_object_zalloc(&device->vk, pAllocator, sizeof(*image),
                             VK_OBJECT_TYPE_IMAGE);

    image->type = pCreateInfo->imageType;
    image->extent = pCreateInfo->extent;
    image->vk_format = pCreateInfo->format;
    image->levels = pCreateInfo->mipLevels;

    unsigned offset = 0;

    for (unsigned l = 0; l <= image->levels; ++l) {
        unsigned width = u_minify(image->extent.width, l);
        unsigned height = u_minify(image->extent.height, l);

        if (image->drm_format_mod == DRM_FORMAT_MOD_APPLE_64X64_MORTON_ORDER)
        {
            width = ALIGN_POT(width, 64);
            height = ALIGN_POT(height, 64);
        }

        image->slices[l].line_stride =
            util_format_get_stride(vk_format_to_pipe_format(image->vk_format), width);

        image->slices[l].offset = offset;
        offset += ALIGN_POT(image->slices[l].line_stride * height, 0x80);
    }

    *pImage = agxv_image_to_handle(image);

    return VK_SUCCESS;
}

VKAPI_ATTR void VKAPI_CALL
agxv_DestroyImage(VkDevice _device,
                  VkImage _image,
                  const VkAllocationCallbacks *pAllocator)
{
    AGXV_FROM_HANDLE(agxv_device, device, _device);
    AGXV_FROM_HANDLE(agxv_image, image, _image);

    if (image == NULL)
        return;

    vk_object_free(&device->vk, pAllocator, image);
}
